﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace AllenalaMente.Games.Sword
{
    public partial class Sword : UserControl, GameInterface
    {
        private DispatcherTimer updateTimer, startTimer;
        private TimeSpan startTime;
        private Random random;

        private UITimer UIgameTimer;
        private UIScore UIgameScore;

        private int score;
        private int difficulty = 1;
        private int giuste, sbagliate;

        // Sword Data
        private bool IsTouch = false;
        private int MaxPoints = 15;

        private Point mousePosition = new Point();
        private List<Point> dots = new List<Point>();
        private List<Line> lines = new List<Line>();
        private List<Target> targets = new List<Target>();

        public Sword()
        {
            InitializeComponent();

            // Initalize game
            random = new Random();
            score = 0;

            // Start timer
            startTimer = new DispatcherTimer();
            startTimer.Interval = TimeSpan.FromMilliseconds(600);
            startTimer.Tick += new EventHandler(startTimer_Tick);
            startTimer.Start();
            startTime = TimeSpan.FromSeconds(3);
            TextBlockReady.Text = Locale.Strings.Ready;

            // Update timer
            updateTimer = new DispatcherTimer();
            updateTimer.Interval = TimeSpan.FromMilliseconds(45);
            updateTimer.Tick += updateTimer_Tick;
            //updateTimer.Start();

            // Eventi Mouse
            LayoutRoot.MouseLeftButtonDown += SwordSystem_MouseLeftButtonDown;
            LayoutRoot.MouseMove += SwordSystem_MouseMove;
            LayoutRoot.MouseLeftButtonUp += SwordSystem_MouseLeftButtonUp;
            LayoutRoot.MouseLeave += SwordSystem_MouseLeave;

            // UI Game timer
            UIgameTimer = new UITimer(60);
            LayoutRoot.Children.Add(UIgameTimer);
            UIgameTimer.timeOut += game_TimeOut;
            //UIgameTimer.Start();

            // UI Game Score
            UIgameScore = new UIScore();
            LayoutRoot.Children.Add(UIgameScore);
            Canvas.SetLeft(UIgameScore, 750);
        }

        public void Clear()
        {
            LayoutRoot.MouseLeftButtonDown -= SwordSystem_MouseLeftButtonDown;
            LayoutRoot.MouseMove -= SwordSystem_MouseMove;
            LayoutRoot.MouseLeftButtonUp -= SwordSystem_MouseLeftButtonUp;
            LayoutRoot.MouseLeave -= SwordSystem_MouseLeave;

            updateTimer.Tick -= updateTimer_Tick;
            UIgameTimer.timeOut -= game_TimeOut;

            targets.Clear();
            dots.Clear();
            lines.Clear();

            SwordCanvas.Children.Clear();
            TargetCanvas.Children.Clear();
        }

        private void addNewTarget()
        {
            if (TargetCanvas.Children.Count > 2)
                return;

            Target t = new Target();
            TargetCanvas.Children.Add(t);
            t.SetPosition(new Point(random.Next(100, 700), 200));

            Canvas.SetLeft(t, t.position.X);
            Canvas.SetTop(t, t.position.Y);
            t.IsHitTestVisible = false;

            targets.Add(t);
        }

        private void addSign(Point p)
        {
            dots.Add(p); // Aggiunge il nuovo punto

            // Costruisce la scia
            if (dots.Count > 2)
            {
                SwordCanvas.Children.Clear();
                lines.Clear();

                for (int i = 1; i < dots.Count; i++)
                {
                    Line l = new Line();
                    l.X1 = dots[i - 1].X;
                    l.Y1 = dots[i - 1].Y;
                    l.X2 = dots[i].X;
                    l.Y2 = dots[i].Y;

                    l.StrokeThickness = i + 2;
                    l.Stroke = new SolidColorBrush(Colors.Yellow);

                    l.Width = 800;
                    l.Height = 400;

                    lines.Add(l);
                }

                for (int i = 0; i < lines.Count; i++)
                {
                    SwordCanvas.Children.Add(lines[i]);
                }
            }
        }

        private void IncreaseScore(int amount)
        {
            score += amount;
            if (score < 0) score = 0;                   

            UIgameScore.SetScore(score);
        }

        #region Events

        private void startTimer_Tick(object sender, EventArgs e)
        {
            startTime = startTime.Subtract(TimeSpan.FromSeconds(1));
            if (startTime.Seconds < 2)
                TextBlockReady.Text = Locale.Strings.GO;
            if (startTime.Seconds < 1)
            {
                // The countdown is finished, the game can start
                startTimer.Tick -= startTimer_Tick;
                CanvasCountdown.Visibility = Visibility.Collapsed;
                updateTimer.Start();
                UIgameTimer.Start();

                addNewTarget();
            }
        }

        // Update
        private void updateTimer_Tick(object sender, EventArgs e)
        {
            UpdateTracing();

            UpdateTargets();

            //CheckCollision();

            textBlockDegug.Text = "isTouch=" + IsTouch.ToString() + " Dots: " + dots.Count + " Lines: " + lines.Count + " Targets: " + targets.Count + " Diff " + difficulty;
        }

        private void UpdateTracing()
        {
            if (dots.Count > 0)
            {
                dots.Remove(dots.First()); // Rimuove il punto più vecchio

                // Ricostruisce la scia

                SwordCanvas.Children.Clear();
                lines.Clear();

                for (int i = 1; i < dots.Count; i++)
                {
                    Line l = new Line();
                    l.X1 = dots[i - 1].X;
                    l.Y1 = dots[i - 1].Y;
                    l.X2 = dots[i].X;
                    l.Y2 = dots[i].Y;

                    l.StrokeThickness = i;
                    l.Stroke = new SolidColorBrush(Colors.Yellow);
                    l.IsHitTestVisible = false;

                    l.Width = 800;
                    l.Height = 400;

                    lines.Add(l);

                    SwordCanvas.Children.Add(l);
                }

                //for (int i = 0; i < lines.Count; i++)
                //{
                //    SwordCanvas.Children.Add(lines[i]);
                //}
            }
        }

        private void UpdateTargets()
        {
            for (int i = 0; i < targets.Count; i++)
            {
                Target t = targets[i];

                t.speed = (t.position.Y - 30) / 5;

                t.position.X += (t.direction.X * t.speed);
                t.position.Y += (t.direction.Y * t.speed);

                t.SetAngle(t.speed);
                t.SetPosition(t.position);

                // Limite X
                if (t.position.X < 30)
                {
                    t.position.X = 30;
                    t.direction.X *= -1;
                }
                else
                if (t.position.X > 730)
                {
                    t.position.X = 730;
                    t.direction.X *= -1;
                }

                // Limite Y
                if (t.position.Y < 35)
                {
                    t.position.Y = 35;
                    t.speed *= 2;
                    t.direction.Y *= -1;
                    t.direction.X /= 2;
                }
                else
                if (t.position.Y > 500)
                {
                    t.position.Y = 500;
                    t.direction.Y *= -1;
                    t.isActive = true;
                    t.CanvasTarget.Opacity = 1;
                    t.direction.X = 0.1 * random.Next(-8, 8);

                    t.SetType(t.type);
                    t.TextBlockTarget.Text = "";
                }

                // Update Position
                Canvas.SetLeft(t, t.position.X);
                Canvas.SetTop(t, t.position.Y);

                CheckCollision(t);
            }

        }

        private void CheckCollision(Target t)
        {
            //for (int j = 0; j < targets.Count; j++)
            //{
            //    Target t = targets[j];
           

                for (int i = lines.Count - 1; i > 0; i--)
                {
                    if (t.isActive && t.Intersect(lines[i]))
                    {
                        t.Hide();
                        t.isActive = false;


                        if (t.type == TargetType.normal)
                        {
                            giuste++;

                            // Punti: 100 + (diff. lev * 5)
                            int points = 20 + (difficulty * 5);
                            t.TextBlockTarget.Foreground = new SolidColorBrush(Colors.White);
                            t.TextBlockTarget.Text = "+" + points;
                            IncreaseScore(points);

                            if ((giuste % (5 * difficulty)) == 0)
                            {
                                difficulty++;
                                if (difficulty > 5) difficulty = 5;

                                if(targets.Count < 6) addNewTarget();

                                if (difficulty == 2) targets.Last().SetType(TargetType.bomb);
                                if (difficulty == 5) targets.Last().SetType(TargetType.bomb);
                                //if (difficulty == 6) targets.Last().SetType(TargetType.bomb);                                
                            }
                        }
                        else
                        {
                            sbagliate++;
                            IncreaseScore(-50);
                            t.TextBlockTarget.Foreground = new SolidColorBrush(Colors.Red);
                            t.TextBlockTarget.Text = "-50";
                        }

                        return;
                    }
                }
             //}
            }        

        // Events

        void SwordSystem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            IsTouch = true;
        }

        void SwordSystem_MouseLeave(object sender, MouseEventArgs e)
        {
            IsTouch = false;
        }

        void SwordSystem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            IsTouch = false;
        }

        void SwordSystem_MouseMove(object sender, MouseEventArgs e)
        {
            if (IsTouch)
            {
                Point mp = e.GetPosition(LayoutRoot);

                if (mousePosition.X != mp.X && mousePosition.Y != mp.Y)
                {
                    if (dots.Count < MaxPoints) addSign(mp);

                    mousePosition = mp;
                }
            }
        }

        // End Game - Time Out
        public event GameEvent GameEnd;

        private void game_TimeOut(object sender, EventArgs e)
        {
            // Finito il tempo
            GameEventArgs gea = new GameEventArgs();
            gea.reason = GameCloseReason.Timeout;
            gea.score = this.score;
            gea.giuste = giuste;
            gea.sbagliate = sbagliate;

            Clear();

            if (GameEnd != null)
                GameEnd(this, gea);
        }

        #endregion

        #region Animations

        public void Show(UIElement element)
        {
            DoubleAnimation doubleAnimation = new DoubleAnimation();
            doubleAnimation.From = 0;
            doubleAnimation.To = 1;
            doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));

            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Opacity"));
            Storyboard.SetTarget(doubleAnimation, element);

            Storyboard sb = new Storyboard();
            sb.Children.Add(doubleAnimation);
            sb.Begin();
        }

        public void Hide(UIElement element)
        {
            DoubleAnimation doubleAnimation = new DoubleAnimation();
            doubleAnimation.From = 1;
            doubleAnimation.To = 0;
            doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1.0));

            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Opacity"));
            Storyboard.SetTarget(doubleAnimation, element);

            Storyboard sb = new Storyboard();
            sb.Children.Add(doubleAnimation);
            sb.Begin();
        }

        #endregion
    }
}
